/**
 * 动态路由处理
 * 根据接口返回的菜单列表注册动态路由
 */
import type { Router, RouteRecordRaw } from "vue-router";
import type { AppRouteRecord } from "@/types/router";
import { saveIframeRoutes } from "./menuToRouter";
import { RoutesAlias } from "../routesAlias";
import { h } from "vue";
import { useMenuStore } from "@/store/modules/menu";

/**
 * 动态导入 views 目录下所有 .vue 组件
 */
const modules: Record<string, () => Promise<any>> = import.meta.glob(
  "../../views/**/*.vue",
);

/**
 * 注册异步路由
 * 将接口返回的菜单列表转换为 Vue Router 路由配置，并添加到传入的 router 实例中
 * @param router Vue Router 实例
 * @param menuList 接口返回的菜单列表
 */
export function registerDynamicRoutes(
  router: Router,
  menuList: AppRouteRecord[],
): void {
  // 用于局部收集 iframe 类型路由
  const iframeRoutes: AppRouteRecord[] = [];
  // 收集路由移除函数
  const removeRouteFns: (() => void)[] = [];

  // 检测菜单列表中是否有重复路由
  checkDuplicateRoutes(menuList);

  // 遍历菜单列表，注册路由
  menuList.forEach((route) => {
    // 只有还没注册过的路由才进行注册
    if (route.name && !router.hasRoute(route.name)) {
      const routeConfig = convertRouteComponent(route, iframeRoutes);

      // 将所有动态路由作为根路由的子路由注册，确保左侧菜单显示
      try {
        const removeRouteFn = router.addRoute(
          "Root",
          routeConfig as RouteRecordRaw,
        );
        removeRouteFns.push(removeRouteFn);
        console.log(
          `[路由注册] 成功注册路由: ${String(route.name)} -> ${route.path}`,
        );
      } catch (error) {
        console.error(`[路由注册] 注册路由失败: ${String(route.name)}`, error);
      }
    }
  });

  // 将移除函数存储到 store 中
  const menuStore = useMenuStore();
  menuStore.addRemoveRouteFns(removeRouteFns);

  // 保存 iframe 路由
  saveIframeRoutes(iframeRoutes);
  console.log(`[路由注册] 共注册 ${removeRouteFns.length} 个动态路由`);
}

/**
 * 路径解析函数：处理父路径和子路径的拼接
 */
function resolvePath(parent: string, child: string): string {
  return [parent.replace(/\/$/, ""), child.replace(/^\//, "")]
    .filter(Boolean)
    .join("/");
}

/**
 * 检测菜单中的重复路由（包括子路由）
 */
function checkDuplicateRoutes(routes: AppRouteRecord[], parentPath = ""): void {
  // 用于检测动态路由中的重复项
  const routeNameMap = new Map<string, string>(); // 路由名称 -> 路径
  const componentPathMap = new Map<string, string>(); // 组件路径 -> 路由信息

  const checkRoutes = (routes: AppRouteRecord[], parentPath = "") => {
    routes.forEach((route) => {
      // 处理路径拼接
      const currentPath = route.path || "";
      const fullPath = resolvePath(parentPath, currentPath);

      // 名称重复检测
      if (route.name) {
        if (routeNameMap.has(String(route.name))) {
          console.warn(`[路由警告] 名称重复: "${String(route.name)}"`);
        } else {
          routeNameMap.set(String(route.name), fullPath);
        }
      }

      // 组件路径重复检测
      if (route.component) {
        const componentPath = getComponentPathString(route.component);

        if (componentPath && componentPath !== RoutesAlias.Layout) {
          const componentKey = `${parentPath}:${componentPath}`;

          if (componentPathMap.has(componentKey)) {
            console.warn(`[路由警告] 路径重复: "${componentPath}"`);
          } else {
            componentPathMap.set(componentKey, fullPath);
          }
        }
      }

      // 递归处理子路由
      if (route.children?.length) {
        checkRoutes(route.children, fullPath);
      }
    });
  };

  checkRoutes(routes, parentPath);
}

/**
 * 获取组件路径的字符串表示
 */
function getComponentPathString(component: any): string {
  if (typeof component === "string") {
    return component;
  }

  // 对于其他别名路由，获取组件名称
  for (const key in RoutesAlias) {
    if (RoutesAlias[key as keyof typeof RoutesAlias] === component) {
      return `RoutesAlias.${key}`;
    }
  }

  return "";
}

/**
 * 将驼峰命名转换为短横线命名
 * 例如: merchantBalance -> merchant-balance
 */
function camelToKebabCase(str: string): string {
  return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}

/**
 * 根据组件路径动态加载组件
 * 支持WMS模块的路径映射和驼峰命名转换
 * 如果找不到对应组件，自动使用动态组件
 * @param componentPath 组件路径（不包含 ../../views 前缀和 .vue 后缀）
 * @param routeName 当前路由名称（用于错误提示）
 * @returns 组件加载函数
 */
function loadComponent(
  componentPath: string,
  routeName: string,
): () => Promise<any> {
  // 如果路径为空，返回art-design-pro风格的提示组件
  if (componentPath === "") {
    return () => Promise.resolve({
      name: "EmptyPathComponent",
      template: `
        <div style="min-height: 300px; display: flex; align-items: center; justify-content: center;">
          <el-result 
            icon="info" 
            title="页面组件未配置" 
            :sub-title="'路由名称: ${routeName}'"
          >
            <template #extra>
              <el-button type="primary" @click="$router.push('/')">返回首页</el-button>
            </template>
          </el-result>
        </div>
      `
    });
  }

  // 确保路径以 / 开头
  const normalizedPath = componentPath.startsWith("/")
    ? componentPath
    : "/" + componentPath;

  // 构建可能的路径列表，按优先级排序
  const possiblePaths: string[] = [];

  // 1. 原始路径（直接匹配）
  possiblePaths.push(`../../views${normalizedPath}.vue`);
  possiblePaths.push(`../../views${normalizedPath}/index.vue`);

  // 2. 转换路径中的驼峰命名为短横线命名
  const pathSegments = normalizedPath.split("/");
  const kebabCaseSegments = pathSegments.map((segment) =>
    segment ? camelToKebabCase(segment) : segment,
  );
  const kebabCasePath = kebabCaseSegments.join("/");

  if (kebabCasePath !== normalizedPath) {
    possiblePaths.push(`../../views${kebabCasePath}.vue`);
    possiblePaths.push(`../../views${kebabCasePath}/index.vue`);
  }

  // 3. 特殊处理：只转换最后一个路径段（文件名）
  const lastSegmentIndex = pathSegments.length - 1;
  if (lastSegmentIndex > 0 && pathSegments[lastSegmentIndex]) {
    const partialKebabPath = [...pathSegments];
    partialKebabPath[lastSegmentIndex] = camelToKebabCase(
      pathSegments[lastSegmentIndex],
    );
    const partialKebabCasePath = partialKebabPath.join("/");

    if (
      partialKebabCasePath !== normalizedPath &&
      partialKebabCasePath !== kebabCasePath
    ) {
      possiblePaths.push(`../../views${partialKebabCasePath}.vue`);
      possiblePaths.push(`../../views${partialKebabCasePath}/index.vue`);
    }
  }

  // 4. WMS模块特殊处理：尝试 /wms/basic/ 路径变体
  if (
    normalizedPath.startsWith("/wms/") &&
    !normalizedPath.includes("/basic/")
  ) {
    // 尝试将 /wms/xxx 转换为 /wms/basic/xxx
    const wmsBasicPath = normalizedPath.replace("/wms/", "/wms/basic/");
    possiblePaths.push(`../../views${wmsBasicPath}.vue`);
    possiblePaths.push(`../../views${wmsBasicPath}/index.vue`);

    // 同时尝试驼峰转换
    const wmsBasicKebabPath = wmsBasicPath
      .split("/")
      .map((segment) => (segment ? camelToKebabCase(segment) : segment))
      .join("/");
    if (wmsBasicKebabPath !== wmsBasicPath) {
      possiblePaths.push(`../../views${wmsBasicKebabPath}.vue`);
      possiblePaths.push(`../../views${wmsBasicKebabPath}/index.vue`);
    }
  }

  // 5. 尝试加载组件
  for (const path of possiblePaths) {
    const module = modules[path];
    if (module) {
      console.log(`[路由成功] 找到组件：${routeName}，路径: ${path}`);
      // 🛡️ 安全包装：确保模块正常工作
      return () => module().then((component: any) => {
        if (!component || !component.default) {
          console.error(`[组件加载] 组件模块无效: ${path}`);
          throw new Error(`Invalid component module: ${path}`);
        }
        return component.default;
      }).catch((error: any) => {
        console.error(`[组件加载] 加载失败: ${path}`, error);
        // 🔧 使用art-design-pro风格的错误处理组件
        return {
          name: "ComponentLoadFailure", 
          template: `
            <div style="min-height: 300px; display: flex; align-items: center; justify-content: center;">
              <el-result 
                icon="warning" 
                title="组件加载失败" 
                :sub-title="'路径: ${path}, 路由: ${routeName}'"
              >
                <template #extra>
                  <el-button type="primary" @click="$router.push('/')">返回首页</el-button>
                  <el-button @click="location.reload()">重新加载</el-button>
                </template>
              </el-result>
            </div>
          `
        };
      });
    }
  }

  // 所有路径都失败，返回art-design-pro风格的组件不存在提示
  console.log(
    `[组件不存在] 未找到静态组件：${routeName}，路径: ${normalizedPath}`,
  );

  // 返回art-design-pro风格的组件不存在提示
  return () => Promise.resolve({
    name: "ComponentNotFound",
    template: `
      <div style="min-height: 300px; display: flex; align-items: center; justify-content: center;">
        <el-result 
          icon="404" 
          title="页面组件不存在" 
          :sub-title="'路径: ${normalizedPath}'"
        >
          <template #extra>
            <el-button type="primary" @click="$router.push('/')">返回首页</el-button>
          </template>
        </el-result>
      </div>
    `
  });
}

/**
 * 转换后的路由配置类型
 */
interface ConvertedRoute extends Omit<RouteRecordRaw, "children"> {
  id?: number;
  children?: ConvertedRoute[];
  component?: RouteRecordRaw["component"] | (() => Promise<any>);
}

/**
 * 转换路由组件配置
 */
function convertRouteComponent(
  route: AppRouteRecord,
  iframeRoutes: AppRouteRecord[],
  depth = 0,
): ConvertedRoute {
  const { component, children, ...routeConfig } = route;

  // 基础路由配置
  const converted: ConvertedRoute = {
    ...routeConfig,
    component: undefined,
  };

  // 是否为一级菜单
  const isFirstLevel =
    depth === 0 &&
    route.children?.length === 0 &&
    component !== RoutesAlias.Layout;

  if (route.meta.isIframe) {
    handleIframeRoute(converted, route, iframeRoutes);
  } else if (isFirstLevel) {
    // 对于一级菜单，将其作为layout的子路由，确保左侧菜单显示
    handleLayoutRoute(converted, route, component as string);
  } else {
    handleNormalRoute(converted, component as string, String(route.name));
  }

  // 递归时增加深度
  if (children?.length) {
    converted.children = children.map((child) =>
      convertRouteComponent(child, iframeRoutes, depth + 1),
    );
  }

  return converted;
}

/**
 * 处理 iframe 类型路由
 */
function handleIframeRoute(
  converted: ConvertedRoute,
  route: AppRouteRecord,
  iframeRoutes: AppRouteRecord[],
): void {
  converted.path = `/outside/iframe/${String(route.name)}`;
  converted.component = () => import("@/views/outside/Iframe.vue");
  iframeRoutes.push(route);
}

/**
 * 处理一级菜单路由
 */
function handleLayoutRoute(
  converted: ConvertedRoute,
  route: AppRouteRecord,
  component: string | undefined,
): void {
  // 直接加载组件，不再包装layout，因为已经作为根路由的子路由
  converted.component = loadComponent(component as string, String(route.name));
  // 保持原路径，不做特殊处理
  // converted.path = route.path;
}

/**
 * 处理普通路由
 * 参考Art Design Pro的路由处理模式
 */
function handleNormalRoute(
  converted: ConvertedRoute,
  component: string | undefined,
  routeName: string,
): void {
  if (component) {
    // 先尝试RoutesAlias映射
    const aliasComponent = RoutesAlias[
      component as keyof typeof RoutesAlias
    ] as unknown as RouteRecordRaw["component"];

    if (aliasComponent) {
      // 如果在RoutesAlias中找到，使用别名组件
      console.log(
        `[路由别名] 使用RoutesAlias映射: ${component} -> ${String(aliasComponent)}`,
      );
      converted.component = loadComponent(String(aliasComponent), routeName);
    } else {
      // 否则使用普通的组件加载
      console.log(`[路由加载] 直接加载组件: ${component}`);
      converted.component = loadComponent(component as string, routeName);
    }
  } else {
    // 如果没有组件，使用默认的空组件
    converted.component = loadComponent("", routeName);
  }
}
